﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using Vector2 = Microsoft.Xna.Framework.Vector2;
using Vector4 = Microsoft.Xna.Framework.Vector4;
namespace LevelEditor
{
    public partial class TerrainRuleEditor : Form
    {
        private RuleType CurrentRuleType
        {
            get { return CurrentRule.type; }
            set 
            {
                CurrentRule.type = value;
                comboBox1.Text = value.ToString();
            }
        }
        
        private TerrainRule CurrentRule;

        // flag used to stop an infinite recursive loop when the user selectes a direction
        int timesRaised;

        public TerrainRuleEditor(TerrainRule rule)
        {
            this.CurrentRule = rule;
            Init();
            switch (rule.type)
            {
                case RuleType.AboveAltitude:
                    numericUpDown1.Value = (int)(float)rule.Value;
                    break;
                case RuleType.BelowAltitude:
                    goto case RuleType.AboveAltitude;
                case RuleType.AltitudeRange:
                    numericUpDown1.Value = (decimal)((Microsoft.Xna.Framework.Vector2)rule.Value).X;
                    numericUpDown2.Value = (decimal)((Microsoft.Xna.Framework.Vector2)rule.Value).Y;
                    break;
                case RuleType.FacesDirection:
                    {
                        Microsoft.Xna.Framework.Vector4 dir = (Microsoft.Xna.Framework.Vector4)rule.Value;
                        topViewDirection.Value = new Vector2(dir.X, dir.Z);
                        sideViewDirection.Value = new Vector2(dir.Z, dir.Y);
                        numericUpDown1.Value = (decimal)dir.W;
                    }
                    break;
            }
            exclusiveCheckBox.Checked = rule.exclusive;
            comboBox1.Text = rule.type.ToString();
            UpdateTypeData();
        }

        void Init()
        {

            InitializeComponent();
            
            comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged;

            topViewDirection.ValueChanged += topViewDirection_ValueChanged;
            sideViewDirection.ValueChanged += sideViewDirection_ValueChanged;
            foreach (Control c in groupBox1.Controls)
                c.Visible = false;
            groupBox1.Enabled = false; 
        }

        /// <summary>
        /// Updates the controls placed on the form based on the current selected type
        /// </summary>
        void UpdateTypeData()
        {
            CurrentRuleType = (RuleType)Enum.Parse(typeof(RuleType), comboBox1.Text);
            if (CurrentRuleType != RuleType.Underwater && CurrentRuleType != RuleType.None)
                groupBox1.Enabled = true;
            foreach (Control c in groupBox1.Controls)
                c.Visible = false;
            switch (CurrentRuleType)
            {
                case RuleType.None:
                    groupBox1.Enabled = false;
                    break;
                case RuleType.AboveAltitude:
                    minAltLabel.Visible = true;
                    minAltLabel.Text = "Altitude";
                    numericUpDown1.Visible = true;
                    break;
                case RuleType.BelowAltitude:
                    minAltLabel.Visible = true;
                    minAltLabel.Text = "Altitude";
                    numericUpDown1.Visible = true;
                    break;
                case RuleType.AltitudeRange:
                    minAltLabel.Visible = maxAltLabel.Visible = true;
                    minAltLabel.Text = "Min Altitude";
                    numericUpDown1.Visible = true;
                    numericUpDown2.Visible = true;
                    break;
                case RuleType.Underwater:
                    goto case RuleType.None;
                case RuleType.FacesDirection:
                    {
                        minAltLabel.Text = "Bias";                        
                        Point location = topViewLabel.Location;
                        topViewDirection.Visible = sideViewDirection.Visible = minAltLabel.Visible = numericUpDown1.Visible = true;
                        location.Y = topViewDirection.Top - topViewLabel.Height;
                        topViewLabel.Location = location;

                        location = sideViewLabel.Location;
                        location.Y = sideViewDirection.Top - sideViewLabel.Height;
                        sideViewLabel.Location = location;

                        topViewLabel.Visible = sideViewLabel.Visible = true;
                    }
                    break;
            }
            exclusiveCheckBox.Visible = true;
        }
        
        void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateTypeData();
        }

        void sideViewDirection_ValueChanged(object sender, EventArgs e)
        {
            if (timesRaised > 2)
            {
                timesRaised = 0;
                return;
            }
            timesRaised++;

            Vector2 value = topViewDirection.Value;
            value.Y = sideViewDirection.Value.X;
            topViewDirection.Value = value;
            topViewDirection.Invalidate();
        }

        void topViewDirection_ValueChanged(object sender, EventArgs e)
        {
            if (timesRaised > 2)
            {
                timesRaised = 0;
                return;
            }
            timesRaised++;

            Vector2 value = sideViewDirection.Value;
            value.X = topViewDirection.Value.Y;
            sideViewDirection.Value = value;
            sideViewDirection.Invalidate();
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            switch (CurrentRuleType)
            {
                case RuleType.FacesDirection:
                    CurrentRule.Value = new Microsoft.Xna.Framework.Vector4(topViewDirection.Value.X, sideViewDirection.Value.Y, sideViewDirection.Value.X, (float)numericUpDown1.Value);
                    break;
                case RuleType.AboveAltitude:
                    CurrentRule.Value = (float)numericUpDown1.Value;
                    break;
                case RuleType.BelowAltitude:
                    CurrentRule.Value = (float)numericUpDown1.Value;
                    break;
                case RuleType.AltitudeRange:
                    CurrentRule.Value = new Vector2((float)numericUpDown1.Value, (float)numericUpDown2.Value);
                    break;
            }
            CurrentRule.exclusive = exclusiveCheckBox.Checked;
            Close();
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            Close();
        }
    }

    /// <summary>
    /// represents a single type of rule
    /// </summary>
    public enum RuleType
    {
        None,
        FacesDirection,
        Underwater,
        AboveAltitude,
        BelowAltitude,
        AltitudeRange,
    }

}
